import time
import traceback
from datetime import datetime
from fastapi import Request, Response
from fastapi.responses import JSONResponse
from starlette.middleware.base import BaseHTTPMiddleware
from ..utils.logger import get_logger

logger = get_logger("middleware.error")
logger.addFileHandler("logs/all.log", level="DEBUG")

class ErrorLogging(BaseHTTPMiddleware):
    """
    错误日志中间件
    捕获所有HTTP错误响应并打印详细的日志信息
    """
    
    async def dispatch(self, request: Request, call_next):
        # 记录方法/url/来源
        request_id = hash(request)
        start_time = time.time()
        client = f"{getattr(request.client, 'host', 'Unknown')}:{getattr(request.client, 'port', '')}"
        logger.debug(f"{request_id:x} | {request.method} {request.url.path} << {client}")
        try:
            # 执行请求
            response = await call_next(request)
            
            # 检查是否是错误响应
            if response.status_code >= 400:
                await self._log_error_response(request, response, start_time)
            
            return response
            
        except Exception as exc:
            # 捕获未处理的异常
            await self._log_unhandled_exception(request, exc, start_time)
            
            # 返回500错误响应
            response = JSONResponse(
                status_code=500,
                content={
                    "detail": "Internal server error",
                    "error": str(exc),
                    "timestamp": datetime.now().isoformat()
                }
            )
            return response
        finally:
            # 记录请求处理的总时间
            duration = time.time() - start_time
            logger.debug(f"{request_id:x} | {response.status_code} >> {client} in {duration:.2f}s")

    async def _log_error_response(self, request: Request, response: Response, start_time: float):
        """记录错误响应的详细信息(捕获后抛出)"""
        duration = time.time() - start_time
        timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        
        # 尝试获取响应体内容
        response_body = ""
        if hasattr(response, 'body') and response.body:
            try:
                response_body = response.body.decode('utf-8')
            except Exception:
                response_body = str(response.body)
        
        # 获取请求体内容
        request_body = await self._get_request_body(request)
        
        error_log = f"""
═════════════════════════════════════════════════════════════════════════════
🚨 API ERROR RESPONSE
─────────────────────────────────────────────────────────────────────────────
Timestamp: {timestamp}
Duration: {duration:.3f}s
Status Code: {response.status_code}
Method: {request.method}
URL: {str(request.url)}
Client IP: {request.client.host if request.client else 'Unknown'}
User Agent: {request.headers.get('user-agent', 'Unknown')}
─────────────────────────────────────────────────────────────────────────────
Request Headers:
{self._format_headers(request.headers)}
─────────────────────────────────────────────────────────────────────────────
Request Body:
{request_body}
─────────────────────────────────────────────────────────────────────────────
Response Headers:
{self._format_headers(response.headers)}
─────────────────────────────────────────────────────────────────────────────
Response Body:
{response_body}
═════════════════════════════════════════════════════════════════════════════
"""
        logger.error(error_log)
    
    async def _log_unhandled_exception(self, request: Request, exc: Exception, start_time: float):
        """记录未处理异常的详细信息(未知错误)"""
        duration = time.time() - start_time
        timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        
        # 获取请求体内容
        request_body = await self._get_request_body(request)
        
        # 获取异常堆栈信息
        stack_trace = ''.join(traceback.format_exception(exc))

        exception_log = f"""
══════════════════════════════════════════════════════════════════════════════
 💥 UNHANDLED EXCEPTION
─────────────────────────────────────────────────────────────────────────────
 Timestamp: {timestamp}
 Duration: {duration:.3f}s
 Exception Type: {type(exc).__name__}
 Exception Message: {str(exc)}
 Method: {request.method}
 URL: {str(request.url)}
 Client IP: {request.client.host if request.client else 'Unknown'}
 User Agent: {request.headers.get('user-agent', 'Unknown')}
──────────────────────────────────────────────────────────────────────────────
 Request Headers:
 {self._format_headers(request.headers)}
──────────────────────────────────────────────────────────────────────────────
 Request Body:
 {request_body}
──────────────────────────────────────────────────────────────────────────────
 Stack Trace:
 {stack_trace}
══════════════════════════════════════════════════════════════════════════════
"""
        logger.critical(exception_log)
    
    async def _get_request_body(self, request: Request) -> str:
        """安全地获取请求体内容"""
        try:
            # 检查是否已经读取过body
            if hasattr(request, '_cached_body'):
                return request._cached_body
            
            # 对于某些请求类型，body可能为空或不可读
            body = await request.body()
            if body:
                body_str = body.decode('utf-8')
                # 缓存body内容，避免重复读取
                request._cached_body = body_str
                return body_str
            else:
                return "(Empty body)"
        except Exception as e:
            return f"(Error reading body: {str(e)})"
    
    def _format_headers(self, headers) -> str:
        """格式化headers为易读的字符串"""
        if not headers:
            return "(No headers)"
        
        formatted_headers = []
        for key, value in headers.items():
            # 隐藏敏感信息
            if key.lower() in ['authorization', 'cookie', 'x-api-key']:
                value = "***HIDDEN***"
            formatted_headers.append(f"  {key}: {value}")
        
        return "\n".join(formatted_headers)
